/**
 * @Copyright: Interactive Business Solution Pte Ltd, Singapore
 * @Author: Li Wen, 2007-12-03
 * @Version: 071207.002
 * Synchronization class, downloads server updated data to local database and uploads local updated data to server
 * Only manager level and administrator level user can upload local data to server database. Salesman level user only
 * can download server data to local
 * UPLOAD 1ST, THEN DOWNLOAD
 */
package com.ibsol.control
{
	import com.ibsol.database.DBConnManager;
	import com.ibsol.model.Company;
	import com.ibsol.model.SystemEnv;
	import com.ibsol.service.CompanyService;
	import com.ibsol.service.SQLExecuteService;
	import com.ibsol.service.TableService;
	
	import flash.data.SQLConnection;
	import flash.errors.IOError;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	
	import mx.collections.ArrayCollection;
	import mx.messaging.Channel;
	import mx.messaging.ChannelSet;
	import mx.messaging.channels.AMFChannel;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.RemoteObject;
	[Bindable]
	public class SyncManager
	{
		//Debug message
		public var log:String = "";
		public var isBusy:Boolean = false;
		//Remote Object related variables
		private var cs:ChannelSet;
		private var roUpload:RemoteObject;
		private var roDownload:RemoteObject;
		//Database connection
		private var _tourixDBConn:SQLConnection;
		//系统表信息
		private var _sysEnv:SystemEnv;
		//全部的上传数据
		public var tableArr:Array=new Array();
		//存储需要修改的pairid字段的数据集合
		public var pairAc:ArrayCollection = new ArrayCollection();
		//从服务器端返回的上传集合个数
		public var backCount:int=0;
		//存储需要上传的集合的个数
		public var rowCount:int=0;
		public var updateType:String = "save";
		
		private var companyService:CompanyService = null;
		private var tableService:TableService = null;
		
		public function SyncManager()
		{
			_tourixDBConn = DBConnManager.getConnection("tourix");
			_sysEnv = SystemManager.getSystemEnv("tourix");
			log = "";
			//Initialize Service
			ChannelInit();
			companyService = new CompanyService();
			tableService = new TableService();
			//Initialize client to server update remote object
			initUploadRO();
			initDownloadRO();
			
		}
		
		private function ChannelInit():void
		{
			var amfChannel:Channel = new AMFChannel("my-amf",_sysEnv.serverAddr + "/tourixDS/messagebroker/amf");
			cs = new ChannelSet();
			cs.addChannel(amfChannel);
		}
		//Upload first, then Download
		public function startSync():void
		{
			isBusy = true;
			clientToServer();
		}
		// ******* Download Section *******
		private function initDownloadRO():void
		{
			roDownload = new RemoteObject("downloadService");
			roDownload.channelSet = cs;
			roDownload.requestTimeout = 0;
		}
		//连接失败的处理
		private function onDownloadFaultHandler(e:FaultEvent):void{
			this.log += "Download data error: " + e.message + "\n";
			isBusy = false;
		}
		/**
		 * Download data from SERVER to CLIENT
		 * 1. Get XML file from server
		 * 2. Update the updateTime field in the database
		 **/
		public function serverToClient():void
		{
			if(_sysEnv.updateTime != null && _sysEnv.updateTime != "")
			{
				roDownload.addEventListener(ResultEvent.RESULT, onDownloadHandler);
				roDownload.addEventListener(FaultEvent.FAULT, onDownloadFaultHandler);
				var company:Company = companyService.getCompany();
				roDownload.update(company.id, _sysEnv.updateTime);
			}
		}
		//处理服务器端返回的数据并执行更新或保存文件
		private function onDownloadHandler(e:ResultEvent):void{
			var xml:XML = e.result as XML;
			if(xml != null){
				if(updateType == "save"){
					saveXML(xml);
				}
				var sqlUtil:SQLUtil = new SQLUtil();
				sqlUtil.executeXML(xml);
				getServerDate();
				this.log += "Download data successfully\n";
			}
			else
			{
				getServerDate();
				this.log += "Your software is up to date\n";
				return;
			}
			
		}
		//保存更新文件
        public function saveXML(xml:XML):void{
        	try{
        		var updateTime:String = _sysEnv.updateTime;
        		if(updateTime != null && updateTime != ""){
        			updateTime = updateTime.split("-").join("").split(":").join("").split(" ").join("");
        		}
        		var file:File = new File("app-storage:/data/"+updateTime+".xml");
        		var stream:FileStream = new FileStream();
        		stream.open(file,FileMode.WRITE);
        		stream.writeUTFBytes(xml);
        		stream.close();
        	}catch(e:IOError){trace(e);}
        }
        //获得服务器端时间,更新本地数据库的最新更新时间
        public function getServerDate():void{
        	initDownloadRO();
        	roDownload.requestTimeout = 0;
        	roDownload.addEventListener(ResultEvent.RESULT,serverDateHandler);
        	roDownload.addEventListener(FaultEvent.FAULT, serverDateErrorHandler);
			roDownload.getServerDate();
		}
		//获得服务器端时间,更新本地数据库的最新更新时间
		private function serverDateHandler(e:ResultEvent):void{
			var date:String = e.result as String;
			var company:Company = companyService.getCompany();
			var sqlExe:SQLExecuteService = new SQLExecuteService();
			var sql:String = "update system set updateTime='" + date + "' where id =" + company.id;
			sqlExe.executeSQL(sql);
			isBusy = false;
		}
		//获得服务器时间的错误监听
		private function serverDateErrorHandler(event:FaultEvent):void
		{
			trace(event.message);
			this.log += "Server time update error\n";
			isBusy = false;
		}
		// ******* End of Download Section *******
		// ******* Upload Section *******
		private function initUploadRO():void
		{
			roUpload = new RemoteObject("uploadService");
			roUpload.channelSet = cs;
			roUpload.addEventListener(ResultEvent.RESULT,onUploadHandler);
			roUpload.addEventListener(FaultEvent.FAULT,onUploadFaultHandler);
		}
		
		private function onUploadHandler(e:ResultEvent):void
		{
			if(e.result!=null){
				var dt:String=e.result as String;
				//更新offlineOperator和updateTime 为返回的时间
				tableService.updateTables(tableArr);
				//更新system表中更新时间
				//systemEnvService.updateUpdateTime();
				//更新pairid字段
				tableService.updatePairid(pairAc);
				//Alert.show("上传成功","上传提示");
				this.log += "Upload data successfully\n";
				trace(this.log);
				serverToClient();
			}else{
				this.log += "Upload failed\n";
				trace(this.log);
				isBusy = false;
			}
		}
		
		private function onUploadFaultHandler(e:FaultEvent):void{
			trace("远程调用出错:"+e.fault.message);
			//Alert.show("服务器忙，请稍后！","上传提示");
			this.log += "Server is busy, please try later\n";
			isBusy = false;
		}
		//Upload data from CLIENT to SERVER
		public function clientToServer():void
		{
			//Test server connection
			var sc:ConnectionManager = new ConnectionManager(_sysEnv.serverAddr);
			sc.addEventListener("statusChanged", function(e:Event):void
			{
				//sc.status == true
				if(sc.status)
				{
					if(_sysEnv != null)
					{
						//存储需要上传的集合
						tableArr=new Array();
						tableArr=tableService.getAllTables();
						if(tableArr!=null&&tableArr.length!=0){
							for(var i:int=1;i<tableArr.length;i+=2){
								var temparr:ArrayCollection=tableArr[i] as ArrayCollection;
								rowCount+=temparr.length;
							}
							var company:Company = companyService.getCompany();
							//更新pairid
							pairAc = tableService.setPairid(tableArr,company.id,_sysEnv.acc);
							//上传
							roUpload.execute(tableArr,company.id);
						}else{
							this.log += "No data is uploaded\n";
							serverToClient();
							}
					}
				}else{
					this.log += "Cannot connect to server\n";
					isBusy = false;
					}
			});
		}
		// ******* End of Upload Section ******
		
	}
}